from PyQt5.QtWidgets import QMainWindow
from PyQt5.QtCore import Qt
from PyQt5 import QtCore
import sys
from io import StringIO

from guis.designer_ui.MainWindow import Ui_MainWindow

from businesses import Business_Mod


class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        # 搭建基本的界面样式
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)

        # 对界面信息进行微调
        # 设置窗口标题
        self.setWindowTitle('Main Window')

        # 初始化业务模块
        self.business = Business_Mod() #这里初始化总业务

        # 绑定事件
        self.ui.run_btn.clicked.connect(self.run_script)

        # region 下面是关于命令行的代码
        self.ui.input_cmd.append(">>> ")
        # 初始化状态变量
        self.gap_num = 0
        self.code_block = ""
        self.key_words = ("for", "if", "def", "class")
        self.gap_len = 4
        self.gap = self.gap_len * " "
        # 创建一个缓冲区对象，并将标准输出重定向到该缓冲区
        self.buffer = StringIO()
        sys.stdout = self.buffer

        self.history = []
        self.history_index = 0

        self.old_handle = self.ui.input_cmd.keyPressEvent
        self.ui.input_cmd.keyPressEvent = self.handle_key_press
        # endregion

        # 下面式构建扩展的tools
        self.exten_tools_gui = {}
        self.build_tools()


    def count_black(self,line):
        cnt = 0
        for w in line:
            if w == ' ':
                cnt += 1
            else:
                return cnt//self.gap_len

    # 命令行中的操作代码
    def handle_key_press(self, event):
        if event.key() == QtCore.Qt.Key_Return or event.key() == QtCore.Qt.Key_Enter:
            # 获取当前行的文本内容
            current_line = self.ui.input_cmd.textCursor().block().text()[4:]
            strip_cur_line = current_line.strip()
            # 如果不是代码块，是命令行
            if not self.gap_num:
                # 如果以关键词开头
                if strip_cur_line.startswith(self.key_words):
                    # 如果当前行以关键词开头且不在代码块中，则进入代码块模式
                    self.gap_num += 1
                    self.code_block = strip_cur_line
                    self.ui.input_cmd.append("<<< " + self.gap * self.gap_num)
                    return
                    # self.ui.input_cmd.append(f">>> {current_line}")
                # 如果不是 则正常执行
                else:
                    input_box_content = self.ui.input_cmd.toPlainText()

                    self.ui.output_cmd.append(input_box_content)

                    # 加入历史存留
                    self.history.append(input_box_content)
                    self.history_index = len(self.history)

                    # 清空输入框
                    self.ui.input_cmd.clear()
                    if '=' in strip_cur_line.replace('==',''):
                        result = self.business.run_(strip_cur_line, 'script')
                    else:
                        result = self.business.run_(strip_cur_line,'cmd')
                    self.refresh_var_list()
                    # 在文本框中添加输出结果，并在下一行加上 '>>>' 标记

                    if result != '':
                        self.ui.output_cmd.append(result)

                    output = self.buffer.getvalue()
                    if output != '':
                        self.ui.output_cmd.append(output)

                    # 清空缓冲区
                    self.buffer.truncate(0)
                    self.buffer.seek(0)

                    self.ui.input_cmd.append(f">>> ")

                    # cursor.setObject(None)
            else:
                if strip_cur_line:
                    # current_line
                    self.gap_num = self.count_black(current_line)
                    # 如果以关键词开头则添加gap_num
                    if strip_cur_line.startswith(self.key_words):
                        self.gap_num += 1
                    # 如果在代码块中，将当前行添加到代码块中
                    self.code_block += '\n' + current_line

                    self.ui.input_cmd.append(f"<<< " + self.gap * self.gap_num)
                    return
                    # self.ui.input_cmd.append(current_line)
                else:
                    # 如果不在代码块中且不以关键词开头，则执行当前行的代码并获取结果
                    self.ui.output_cmd.append(">>> ")
                    self.ui.output_cmd.append(self.code_block)

                    # 加入历史存留
                    self.history.append('>>> ' + self.code_block.split('\n')[-1])
                    self.history_index = len(self.history)

                    # 清空输入框
                    self.ui.input_cmd.clear()

                    result = self.business.run_(self.code_block, 'script')
                    self.refresh_var_list()
                    output = self.buffer.getvalue()
                    if output != '':
                        self.ui.output_cmd.append(output)

                    # 清空缓冲区
                    self.buffer.truncate(0)
                    self.buffer.seek(0)

                    self.gap_num = 0
                    # 在文本框中添加输出结果，并在下一行加上 '>>>' 标记
                    self.ui.input_cmd.append(result)
                    self.ui.input_cmd.append(f">>> ")
                    # self.ui.input_cmd.append("")

            # 将滚动条滚动到最底部
            scrollbar = self.ui.input_cmd.verticalScrollBar()
            scrollbar.setValue(scrollbar.maximum())

            # 清空当前行的内容
            # self.ui.input_cmd.textCursor().block().setPlainText("")

            # 返回True表示事件已经处理
            return

        if self.gap_num == 0 and event.key() == Qt.Key_Up:
            if self.history_index > 0:
                self.history_index -= 1
                self.ui.input_cmd.setPlainText(self.history[self.history_index])

        elif self.gap_num == 0 and event.key() == Qt.Key_Down:
            if self.history_index < len(self.history):
                self.history_index += 1
                if self.history_index == len(self.history):
                    self.ui.input_cmd.clear()
                else:
                    self.ui.input_cmd.setPlainText(self.history[self.history_index])

        # 默认情况下，返回False表示事件继续传递给基类处理
        self.old_handle(event)

    # 维护脚本区
    def run_script(self):
        # 搜集code
        code = self.ui.script_edit.toPlainText()     # 从GUI组件获取数据--作为业务的输入
        # 运行
        self.business.run_(code,code_type='script')  # 调用业务模块中的功能模块 -- 重要示范

        # 显示结果
        output = self.buffer.getvalue()
        if output != '':
            self.ui.output_cmd.append(output)

        # 清空缓冲区
        self.buffer.truncate(0)
        self.buffer.seek(0)
        # 更新变量列表
        self.refresh_var_list()

    # 维护变量区
    def refresh_var_list(self):
        # 清除变量区
        self.ui.variables_edit.clear()
        # 生成变量名
        var_str = '\n'.join([f'{k}: {v}' for k,v in self.business.get_variables().items()])
        self.ui.variables_edit.setPlainText(var_str)

    def build_tools(self):
        # 为扩展的tools绑定事件
        self.tools_infos = self.business.get_extend_tools()
        # 根据tools_infos构建工具栏，并且绑定事件

        # 对tools_infos进行for 循环， 在建立对应的action时同时绑定事件

        # 在demo中就绑一个按钮看效果就行
        self.ui.tool_btn.clicked.connect(self.generate_tool_gui)

    def generate_tool_gui(self):

         tool_widget = self.tools_infos['flight']['Tool1']['class'](self.business.get_variables())
         self.exten_tools_gui['Tools'] = tool_widget
         tool_widget.show()

